﻿using IRepositories.Core;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Transactions;
namespace EntityFramework.Data.Core
{
    /// <summary>
    /// 对TransactionScope，让它对同一个数据库不产生msdtc服务
    /// </summary>
    public static class TransactionScopeNoMsdtc
    {
        
        /// <summary>
        /// 产生包裹事务 不去触发MSDTC(分布式事务)
        /// 支持LINQ表提交,并同时返回提交结果到实体
        /// </summary>
        /// <param name="db">数据上下文,多个方法使用的上下文必须是同一个</param>
        /// <param name="isOutermost">是否为最外层，默认为false</param>
        /// <param name="action">处理代码块</param>
        public static void UsingTransactionNoMsdtc(DbContext db, bool isOutermost, Action action)
        {
            var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db).ObjectContext;
            try
            {
                if (objectContext.Connection.State == ConnectionState.Closed)
                    objectContext.Connection.Open();
                
                using (TransactionScope trans = new TransactionScope())
                //using(DbContextTransaction trans=db.Database.BeginTransaction())
                {
                    try
                    {
                        action();
                        trans.Complete();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        trans.Dispose();
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isOutermost)//如果是最外层事务，而将连接关闭
                {
                    objectContext.Connection.Close();
                }
            }
        }
        /// <summary>
        /// 产生包裹事务，它不是最外层的，如果是最外层的需要调用其它重载
        /// </summary>
        /// <param name="db">数据上下文,多个方法使用的上下文必须是同一个</param>
        /// <param name="action">处理代码块</param>
        public static void UsingTransactionNoMsdtc(DbContext db, Action action)
        {
            UsingTransactionNoMsdtc(db, false, action);
        }

        
        /// <summary>
        /// 产生包裹事务，它是最外层的，如果不是最外层的需要调用其它重载
        /// </summary>
        /// <param name="db">数据上下文,多个方法使用的上下文必须是同一个</param>
        /// <param name="action">处理代码块</param>
        /// /// <param name="isOutermost">是否为最外层，默认为true</param>
        public static void UsingTransactionNoMsdtc(IUnitOfWork db, Action action,bool isOutermost=true)
        {
            UsingTransactionNoMsdtc((DbContext)db,isOutermost, action);
        }

    }
}
